<template>
    <div class="dialog">
        <div class="dialog__trigger" @click="open">
            <!-- 触发弹窗 -->
            <slot name="trigger"></slot>
        </div>
        <el-dialog
            v-model="visible"
            :class="customClass"
            :center="center"
            :append-to-body="true"
            :width="width"
            :close-on-click-modal="clickModalClose"
            @closed="close"
        >
            <!-- 弹窗内容 -->
            <template v-if="title" #header>{{ title }}</template>

            <!-- 自定义内容 -->
            <slot>{{ content }}</slot>
            <!-- 底部弹窗页脚 -->
            <template #footer>
                <div class="dialog-footer">
                    <el-button v-if="cancelButtonText" @click="handleEvent('cancel')">
                        {{ cancelButtonText }}
                    </el-button>
                    <el-button v-if="confirmButtonText" type="primary" @click="handleEvent('confirm')">
                        {{ confirmButtonText }}
                    </el-button>
                </div>
            </template>
        </el-dialog>
    </div>
</template>

<script lang="ts" setup>
import { nextTick, provide, ref } from "vue";

const props = withDefaults(
    defineProps<{
        /** 弹窗标题 */
        title?: string;
        /** 弹窗内容 */
        content?: string;
        /** 确认按钮内容 */
        confirmButtonText?: string | boolean;
        /** 取消按钮内容 */
        cancelButtonText?: string | boolean;
        /** 弹窗的宽度 */
        width?: string;
        /** 是否禁用弹窗 */
        disabled?: boolean;
        /** 是否开启异步关闭 */
        async?: boolean;
        /** 点击遮罩层关闭对话窗口 */
        clickModalClose?: boolean;
        /** 是否居中布局 */
        center?: boolean;
        /** 自定义类名 */
        customClass?: string;
    }>(),
    {
        title: "",
        content: "",
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        width: "400px",
        disabled: false,
        async: false,
        clickModalClose: false,
        center: false,
        customClass: ""
    }
);

const emit = defineEmits<{
    (e: "confirm"): void;
    (e: "cancel"): void;
    (e: "close"): void;
    (e: "open"): void;
}>();

const visible = ref(false); // 弹窗是否可见

const handleEvent = (type: "confirm" | "cancel") => {
    emit(type as any);
    if (!props.async || type === "cancel") {
        close();
    }
};

const close = () => {
    visible.value = false;
    nextTick(() => {
        emit("close");
    });
};

const open = () => {
    if (props.disabled) return;
    emit("open");
    visible.value = true;
};

provide("visible", visible);

defineExpose({
    open,
    close
});
</script>

<style scoped lang="scss">
.dialog-body {
    white-space: pre-line;
}
</style>
